原文:[C#] 使用 SpinWait 實作檔案存取 Lock 機制
今天在設計檔案 Lock 機制的時候,發現了一個好物 SpinWait
可以用,比起 Thread.Sleep()
+ While(true)
更來的方便效能也較佳。
多條執行續存取相同檔案時,基本要注意的事情如下:
這邊我設計了一個 FileHandler
來處理這件事情,程式碼如下:
public class FileHandler
{
public void WriteFileContent(string content)
{
using (var fs = waitFileForUse(FileAccess.Write, FileShare.None))
{
fs.SetLength(0);
using (var sw = new StreamWriter(fs, Encoding.UTF8))
{
sw.Write(content);
}
}
}
public string ReadFileContent()
{
using (var fs = waitFileForUse(FileAccess.Read, FileShare.Read))
{
using (var sr = new StreamReader(fs, Encoding.UTF8))
{
return sr.ReadToEnd();
}
}
}
private FileStream waitFileForUse(FileAccess fileAccess, FileShare fileShare)
{
const int maxRetryMilliseconds = 5 * 1000;
string filePath = "note.json";
FileStream fs = null;
SpinWait.SpinUntil(() =>
{
try
{
fs = new FileStream(filePath, FileMode.OpenOrCreate, fileAccess, fileShare);
}
catch { }
return (fs != null);
}, maxRetryMilliseconds);
if (fs == null)
{
throw new IOException($"無法開啟 {filePath}, 已超過 {maxRetryMilliseconds} ms 重試上限");
}
return fs;
}
}
waitFileForUse
這個 Method 裡面我使用了 SpinWait
來去判斷檔案是否可以存取,並設定 Timeout 秒數避免 Deadlock 的問題發生。